Load in Packages

reading twitter ids

tweet_ids <- dir(here("data", "tw"))
here::here("data", "tw")
[1] "C:/Users/Fabio/Documents/git_proj/altright/data/tw"
tweet_ids_list <- list()
for (jj in seq_along(tweet_ids)) {
  tweet_ids_list[[jj]] <- jsonlite::fromJSON(here("data", "tw", tweet_ids[jj]))
}
enframed_tweets <- enframe(tweet_ids_list)
handlers <- c("ABC", "RealAlexJones", "AnnCoulter", "MsBlaireWhite", "navyhato", "BreitbartNews", "Cernovich", "CNN", "FoxNews", "infowars", "Lauren_Southern", "MSNBC", "PrisonPlanet", "TheRebelTV", "RoamingMil","TRobinsonNewEra", "washingtonpost")
ff <- list()
for (jj in seq_along(handlers)) {
  ff[[jj]] <- cbind(enframed_tweets$value[[jj]], handlers[jj])
}
rlist::list.rbind(ff) %>% 
   as.data.frame()

# REPLACE WITH YOUR API KEY
myapikey <- "Rxly3JKWfdM5osWQenXrxzSQX"
# REPLACE WITH YOUR API SECRET
myapisecret <- "u1NPPaUKdMW11dqwhWVwMQIYwmd42YL8fHTM7YhOHiex7YIku5"
# REPLACE WITH YOUR ACCESS TOKEN
myaccesstoken <- "513351911-HnGVTozLlxCQJh4u0kntUajynJDVBHQP1qNFe588"
# REPLACE WITH YOUR ACCESS TOKEN SECRET
myaccesstokensecret <- "mfNN2NVnd9d0WNmS4tZCz85r6swsCZp2H23JdgHMJdXh1"

Load in Data

myTwitterData <- SocialMediaLab::Authenticate("twitter", 
                              apiKey=consumer_key,
                              apiSecret=consumer_secret, 
                              accessToken=access_token,
                              accessTokenSecret=access_secret)# %>%
  Collect(searchTerm="#prayforsouthafrica| #stopwhitegenocide |#whitegenocide| #17states| #unitetheright| #novaeuropa| #tokyo| #buildthewall| #trumpmemes| #trump| #rightwing| #maga| #makeamericagreatagain| #politics| #patriot| #guns",
          numTweets=20000,
          writeToFile=FALSE,
          verbose=TRUE)
Collect(ego = TRUE,
username = myUsernames)

myTwitterData$text <- iconv(myTwitterData$text, to = 'utf-8')

Filter Data

g_twitter_actor <- myTwitterData %>% Create("actor", writeToFile = TRUE)

g_twitter_actor

Recoding

myTwitterData <- Authenticate("twitter", 
                              apiKey=myapikey,
                              apiSecret=myapisecret, 
                              accessToken=myaccesstoken,
                              accessTokenSecret=myaccesstokensecret) %>%
  Collect(ego = TRUE,
username = c("RichardBSpencer", "realDonaldTrump", "mikeenochsback", "MillennialWoes", "thealthype", "JFGariepy"))

Analysis


#install.packages("rtweet")
library(rtweet)


# REPLACE WITH YOUR API KEY
myapikey <- "Rxly3JKWfdM5osWQenXrxzSQX"
# REPLACE WITH YOUR API SECRET
myapisecret <- "u1NPPaUKdMW11dqwhWVwMQIYwmd42YL8fHTM7YhOHiex7YIku5"
# REPLACE WITH YOUR ACCESS TOKEN
myaccesstoken <- "513351911-HnGVTozLlxCQJh4u0kntUajynJDVBHQP1qNFe588"
# REPLACE WITH YOUR ACCESS TOKEN SECRET
myaccesstokensecret <- "mfNN2NVnd9d0WNmS4tZCz85r6swsCZp2H23JdgHMJdXh1"
# Change the next four lines based on your own consumer_key, consume_secret, access_token, and access_secret. 

access_token <- "   513351911-HnGVTozLlxCQJh4u0kntUajynJDVBHQP1qNFe588"
access_secret <- "  mfNN2NVnd9d0WNmS4tZCz85r6swsCZp2H23JdgHMJdXh1"




tw = twitteR::searchTwitter("xD", n = 1e4, since = '2018-01-01', retryOnRateLimit = 1e3)
d = twitteR::twListToDF(tw)


tmls <- rtweet::get_timelines("196168350", n = 20)

rt <- search_tweets(
  "#rstats", n = 18000, include_rts = FALSE
)

flw <- get_followers("196168350", n = 10)

flw_tml <- vector("list", length(flw$user_id))
for (i in seq_along(flw$user_id)) {
  flw_tml[[i]] <- get_timeline(
    flw$user_id[i], n = 10
  )
  if (i %% 56 == 0L) {
    rl <- rate_limit("get_timeline")
    Sys.sleep(as.numeric(rl$reset, "secs"))
  }
  cat(i, " ")
}

at_rdt <- rtweet::search_tweets(
  "to:Cernovich", 
  n = 5e6,
  since = "2017-01-01",
  until = "2018-01-01",
   retryonratelimit = TRUE

tweets <- userTimeline('MillennialWoes', n = 3200)

# convert status object to data frame for easier manipulation
tweetsdf <- twListToDF(tweets)

tweetsdf %>% 
  mutate(date = lubridate::as_date(created)) %>%
  filter(date > lubridate::as_date("2017-01-01") & date < lubridate::as_date("2018-01-01"))
library(httr)

# 1. Find OAuth settings for twitter:
#    https://dev.twitter.com/docs/auth/oauth
oauth_endpoints("twitter")

# 2. Register an application at https://apps.twitter.com/
#    Make sure to set callback url to "http://127.0.0.1:1410/"
#
#    Replace key and secret below
myapp <- oauth_app("twitter",
  key = "TYrWFPkFAkn4G5BbkWINYw",
  secret = "qjOkmKYU9kWfUFWmekJuu5tztE9aEfLbt26WlhZL8"
)

# 3. Get OAuth credentials
twitter_token <- oauth1.0_token(oauth_endpoints("twitter"), myapp)

## 4. Use API
#req <- GET("https://api.twitter.com/1.1/statuses/home_timeline.json",
#  config(token = twitter_token))
#stop_for_status(req)
#content(req)
library(rtweet)
library(igraph)
library(hrbrthemes)
library(ggraph)
library(tidyverse)
rstats <- search_tweets("#antiwhite", n=20000)

# same as previous recipe
filter(rstats, retweet_count > 0) %>% 
  select(screen_name, mentions_screen_name) %>%
  unnest(mentions_screen_name) %>% 
  filter(!is.na(mentions_screen_name)) %>% 
  graph_from_data_frame() -> rt_g


V(rt_g)$node_label <- unname(ifelse(degree(rt_g)[V(rt_g)] > 20, names(V(rt_g)), "")) 
V(rt_g)$node_size <- unname(ifelse(degree(rt_g)[V(rt_g)] > 20, degree(rt_g), 0)) 

ggraph(rt_g, layout = 'linear', circular = TRUE) + 
  geom_edge_arc(edge_width=0.125, aes(alpha=..index..)) +
  geom_node_label(aes(label=node_label, size=node_size),
                  label.size=0, fill="#ffffff66", segment.colour="springgreen",
                  color="slateblue", repel=TRUE, family=font_rc, fontface="bold") +
  coord_fixed() +
  scale_size_area(trans="sqrt") +
  labs(title="Retweet Relationships", subtitle="Most retweeted screen names labeled. Darkers edges == more retweets. Node size == larger degree") +
  theme_graph(base_family=font_rc) +
  theme(legend.position="none")


ggsave(file = here("images","network5.png"))
map_chr2 <- function(x, .f, ...) {
  map(x, .f, ...) %>% map_if(is_empty, ~ NA_character_) %>% flatten_chr()
}
ellipsize <- function(x, n = 20) {
  ifelse(str_length(x) > n,
         paste0(str_sub(x, end = n - 1), "\u2026"),
         str_sub(x, end = n)) %>%
    str_pad(n)
}

mt <- mentions("cnn", n = 200, sinceID = cnn_ids[1])
length(mt)

df <- data_frame(mt = mt) %>%
  mutate(replyToSID = mt %>% map_chr2("replyToSID")) %>%
  filter(replyToSID == target_tweet_id)
df %>%
  mutate(id = mt %>% map_chr2("id"),
         screenName = mt %>% map_chr2("screenName"),
         text = mt %>% map_chr2("text")) %>%
  mutate(text = text %>% substr(13, 140) %>% trimws() %>% ellipsize(30)) %>%
  select(-replyToSID, -mt)

rtweet::lookup_tweets(cnn_ids[1])


##set name of tweeter to look at (this can be changed)
targettwittername <- "cnn"

##get this tweeter's timeline
tmls <- rtweet::get_timeline(targettwittername, n=100, retryonratelimit=TRUE)
##get their user id
targettwitteruserid <- as.numeric(select(rtweet::lookup_users(targettwittername), user_id))
##get ids of their tweets
tweetids <- select(tmls, status_id)
tweetids <- transform(tweetids, status_id_num=as.numeric(status_id))

##get list of followers (who are most likely to reply)
targetfollowers <- data.frame(rtweet::get_followers(targettwittername))

##clean up follower list to exclude those that have never tweeted and restricted access
user_lookup <- rtweet::lookup_users(targetfollowers)
users_with_tweets_and_unprotected <- filter(user_lookup, statuses_count != 0)
users_with_tweets_and_unprotected <- select(filter(users_with_tweets_and_unprotected, protected != "TRUE"), user_id)

targetfollowers <- filter(targetfollowers, user_id %in% users_with_tweets_and_unprotected$user_id)
options(scipen = 999)
getfollowersreplies <- function(x){
  follower <- as.numeric(x[1:500])
  followertl <- data.frame(rtweet::get_timeline(follower, n=3200, retryonratelimit=TRUE))
  followertl <- filter(followertl, reply_to_user_id == targettwitteruserid)
  followertl <- transform(followertl, reply_to_status_id_num=as.numeric(reply_to_user_id))
  join <- inner_join(followertl, tweetids, by=c("reply_to_status_id_num"="status_id_num"))
  replycounts <- data.frame(
                  join %>%
                    group_by(user_id, reply_to_status_id_num) %>%
                    summarise(n=n())
                  )
  return(replycounts)
}

tweet_replies <- do.call("rbind", lapply(targetfollowers$user_id, getfollowersreplies))

ss <- getfollowersreplies(x = targetfollowers$user_id)

flw <- rtweet::get_followers("realDonaldTrump", n = 2)

flw_tml <- vector("list", length(flw$user_id))
for (i in seq_along(flw$user_id)) {
  flw_tml[[i]] <- rtweet::get_timeline(
    flw$user_id[i], n = 3200
  )
  if (i %% 56 == 0L) {
    rl <- rate_limit("get_timeline")
    Sys.sleep(as.numeric(rl$reset, "secs"))
  }
  cat(i, " ")
}
LS0tDQp0aXRsZTogIlR3aXR0ZXIgTWVkaWEgTGFiIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyBMb2FkIGluIFBhY2thZ2VzDQoNCmBgYHtyfQ0KI2luc3RhbGwucGFja2FnZXMoInBhY21hbiIpDQojcGFjbWFuOjpwX2luc3RhbGxfZ2goInN5c3RhdHMvYmlub2N1bGFSIikNCnBhY21hbjo6cF9sb2FkKHRpZHl2ZXJzZSwgbWFncml0dHIsIGhhdmVuLCBnZ3RoZW1lcywgc2pQbG90LCBzam1pc2MsIHNqc3RhdHMsIGJpbm9jdWxhUiwgamFuaXRvciwgaGVyZSwgU29jaWFsTWVkaWFMYWIsIGhyYnJ0aGVtZXMsIGdncmFwaCwgdHdpdHRlUiAsIHB1cnJyLCBzdHJpbmdyLCBqc29ubGl0ZSwgcmxpc3QpDQoNCnJhbmdlMDEgPC0gZnVuY3Rpb24oeCl7KHggLSBtaW4oeCwgbmEucm0gPSBUKSkgLyAobWF4KHgsIG5hLnJtID0gVCkgLSBtaW4oeCwgbmEucm0gPSBUKSl9DQoNCmBgYA0KDQojIHJlYWRpbmcgdHdpdHRlciBpZHMNCg0KYGBge3J9DQojY25uX2lkcyA8LSBmcm9tSlNPTihoZXJlKCJkYXRhIiwgInR3IiwgImNubl9tb250aC5qc29uIikpDQogDQp0d2VldF9pZHMgPC0gZGlyKGhlcmUoImRhdGEiLCAidHciKSkNCmhlcmU6OmhlcmUoImRhdGEiLCAidHciKQ0KDQp0d2VldF9pZHNfbGlzdCA8LSBsaXN0KCkNCmZvciAoamogaW4gc2VxX2Fsb25nKHR3ZWV0X2lkcykpIHsNCiAgdHdlZXRfaWRzX2xpc3RbW2pqXV0gPC0ganNvbmxpdGU6OmZyb21KU09OKGhlcmUoImRhdGEiLCAidHciLCB0d2VldF9pZHNbampdKSkNCn0NCg0KZW5mcmFtZWRfdHdlZXRzIDwtIGVuZnJhbWUodHdlZXRfaWRzX2xpc3QpDQoNCmhhbmRsZXJzIDwtIGMoIkFCQyIsICJSZWFsQWxleEpvbmVzIiwgIkFubkNvdWx0ZXIiLCAiTXNCbGFpcmVXaGl0ZSIsICJuYXZ5aGF0byIsICJCcmVpdGJhcnROZXdzIiwgIkNlcm5vdmljaCIsICJDTk4iLCAiRm94TmV3cyIsICJpbmZvd2FycyIsICJMYXVyZW5fU291dGhlcm4iLCAiTVNOQkMiLCAiUHJpc29uUGxhbmV0IiwgIlRoZVJlYmVsVFYiLCAiUm9hbWluZ01pbCIsIlRSb2JpbnNvbk5ld0VyYSIsICJ3YXNoaW5ndG9ucG9zdCIpDQoNCmZmIDwtIGxpc3QoKQ0KZm9yIChqaiBpbiBzZXFfYWxvbmcoaGFuZGxlcnMpKSB7DQogIGZmW1tqal1dIDwtIGNiaW5kKGVuZnJhbWVkX3R3ZWV0cyR2YWx1ZVtbampdXSwgaGFuZGxlcnNbampdKQ0KfQ0KDQpybGlzdDo6bGlzdC5yYmluZChmZikgJT4lIA0KICAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KYGBgDQoNCg0KYGBge3J9DQoNCiMgUkVQTEFDRSBXSVRIIFlPVVIgQVBJIEtFWQ0KbXlhcGlrZXkgPC0gIlJ4bHkzSktXZmRNNW9zV1FlblhyeHpTUVgiDQojIFJFUExBQ0UgV0lUSCBZT1VSIEFQSSBTRUNSRVQNCm15YXBpc2VjcmV0IDwtICJ1MU5QUGFVS2RNVzExZHF3aFdWd01RSVl3bWQ0MllMOGZIVE03WWhPSGlleDdZSWt1NSINCiMgUkVQTEFDRSBXSVRIIFlPVVIgQUNDRVNTIFRPS0VODQpteWFjY2Vzc3Rva2VuIDwtICI1MTMzNTE5MTEtSG5HVlRvekxseENRSmg0dTBrbnRVYWp5bkpEVkJIUVAxcU5GZTU4OCINCiMgUkVQTEFDRSBXSVRIIFlPVVIgQUNDRVNTIFRPS0VOIFNFQ1JFVA0KbXlhY2Nlc3N0b2tlbnNlY3JldCA8LSAibWZOTjJOVm5kOWQwV05tUzR0WkN6ODVyNnN3c0NacDJIMjNKZGdITUpkWGgxIg0KDQpgYGANCg0KDQojIExvYWQgaW4gRGF0YQ0KDQpgYGB7cn0NCm15VHdpdHRlckRhdGEgPC0gU29jaWFsTWVkaWFMYWI6OkF1dGhlbnRpY2F0ZSgidHdpdHRlciIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBpS2V5PWNvbnN1bWVyX2tleSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwaVNlY3JldD1jb25zdW1lcl9zZWNyZXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWNjZXNzVG9rZW49YWNjZXNzX3Rva2VuLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWNjZXNzVG9rZW5TZWNyZXQ9YWNjZXNzX3NlY3JldCkjICU+JQ0KICBDb2xsZWN0KHNlYXJjaFRlcm09IiNwcmF5Zm9yc291dGhhZnJpY2F8ICNzdG9wd2hpdGVnZW5vY2lkZSB8I3doaXRlZ2Vub2NpZGV8ICMxN3N0YXRlc3wgI3VuaXRldGhlcmlnaHR8ICNub3ZhZXVyb3BhfCAjdG9reW98ICNidWlsZHRoZXdhbGx8ICN0cnVtcG1lbWVzfCAjdHJ1bXB8ICNyaWdodHdpbmd8ICNtYWdhfCAjbWFrZWFtZXJpY2FncmVhdGFnYWlufCAjcG9saXRpY3N8ICNwYXRyaW90fCAjZ3VucyIsDQogICAgICAgICAgbnVtVHdlZXRzPTIwMDAwLA0KICAgICAgICAgIHdyaXRlVG9GaWxlPUZBTFNFLA0KICAgICAgICAgIHZlcmJvc2U9VFJVRSkNCkNvbGxlY3QoZWdvID0gVFJVRSwNCnVzZXJuYW1lID0gbXlVc2VybmFtZXMpDQoNCm15VHdpdHRlckRhdGEkdGV4dCA8LSBpY29udihteVR3aXR0ZXJEYXRhJHRleHQsIHRvID0gJ3V0Zi04JykNCg0KYGBgDQoNCg0KIyBGaWx0ZXIgRGF0YQ0KDQpgYGB7cn0NCmdfdHdpdHRlcl9hY3RvciA8LSBteVR3aXR0ZXJEYXRhICU+JSBDcmVhdGUoImFjdG9yIiwgd3JpdGVUb0ZpbGUgPSBUUlVFKQ0KDQpnX3R3aXR0ZXJfYWN0b3INCmBgYA0KDQoNCiMgUmVjb2RpbmcNCg0KYGBge3J9DQpteVR3aXR0ZXJEYXRhIDwtIEF1dGhlbnRpY2F0ZSgidHdpdHRlciIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBpS2V5PW15YXBpa2V5LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBpU2VjcmV0PW15YXBpc2VjcmV0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjY2Vzc1Rva2VuPW15YWNjZXNzdG9rZW4sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY2Nlc3NUb2tlblNlY3JldD1teWFjY2Vzc3Rva2Vuc2VjcmV0KSAlPiUNCiAgQ29sbGVjdChlZ28gPSBUUlVFLA0KdXNlcm5hbWUgPSBjKCJSaWNoYXJkQlNwZW5jZXIiLCAicmVhbERvbmFsZFRydW1wIiwgIm1pa2Vlbm9jaHNiYWNrIiwgIk1pbGxlbm5pYWxXb2VzIiwgInRoZWFsdGh5cGUiLCAiSkZHYXJpZXB5IikpDQpgYGANCg0KDQojIEFuYWx5c2lzDQoNCmBgYHtyfQ0KDQojaW5zdGFsbC5wYWNrYWdlcygicnR3ZWV0IikNCmxpYnJhcnkocnR3ZWV0KQ0KDQoNCiMgUkVQTEFDRSBXSVRIIFlPVVIgQVBJIEtFWQ0KbXlhcGlrZXkgPC0gIlJ4bHkzSktXZmRNNW9zV1FlblhyeHpTUVgiDQojIFJFUExBQ0UgV0lUSCBZT1VSIEFQSSBTRUNSRVQNCm15YXBpc2VjcmV0IDwtICJ1MU5QUGFVS2RNVzExZHF3aFdWd01RSVl3bWQ0MllMOGZIVE03WWhPSGlleDdZSWt1NSINCiMgUkVQTEFDRSBXSVRIIFlPVVIgQUNDRVNTIFRPS0VODQpteWFjY2Vzc3Rva2VuIDwtICI1MTMzNTE5MTEtSG5HVlRvekxseENRSmg0dTBrbnRVYWp5bkpEVkJIUVAxcU5GZTU4OCINCiMgUkVQTEFDRSBXSVRIIFlPVVIgQUNDRVNTIFRPS0VOIFNFQ1JFVA0KbXlhY2Nlc3N0b2tlbnNlY3JldCA8LSAibWZOTjJOVm5kOWQwV05tUzR0WkN6ODVyNnN3c0NacDJIMjNKZGdITUpkWGgxIg0KIyBDaGFuZ2UgdGhlIG5leHQgZm91ciBsaW5lcyBiYXNlZCBvbiB5b3VyIG93biBjb25zdW1lcl9rZXksIGNvbnN1bWVfc2VjcmV0LCBhY2Nlc3NfdG9rZW4sIGFuZCBhY2Nlc3Nfc2VjcmV0LiANCg0KYWNjZXNzX3Rva2VuIDwtICIJNTEzMzUxOTExLUhuR1ZUb3pMbHhDUUpoNHUwa250VWFqeW5KRFZCSFFQMXFORmU1ODgiDQphY2Nlc3Nfc2VjcmV0IDwtICIJbWZOTjJOVm5kOWQwV05tUzR0WkN6ODVyNnN3c0NacDJIMjNKZGdITUpkWGgxIg0KDQoNCg0KDQp0dyA9IHR3aXR0ZVI6OnNlYXJjaFR3aXR0ZXIoInhEIiwgbiA9IDFlNCwgc2luY2UgPSAnMjAxOC0wMS0wMScsIHJldHJ5T25SYXRlTGltaXQgPSAxZTMpDQpkID0gdHdpdHRlUjo6dHdMaXN0VG9ERih0dykNCg0KDQp0bWxzIDwtIHJ0d2VldDo6Z2V0X3RpbWVsaW5lcygiMTk2MTY4MzUwIiwgbiA9IDIwKQ0KDQpydCA8LSBzZWFyY2hfdHdlZXRzKA0KICAiI3JzdGF0cyIsIG4gPSAxODAwMCwgaW5jbHVkZV9ydHMgPSBGQUxTRQ0KKQ0KDQpmbHcgPC0gZ2V0X2ZvbGxvd2VycygiMTk2MTY4MzUwIiwgbiA9IDEwKQ0KDQpmbHdfdG1sIDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aChmbHckdXNlcl9pZCkpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKGZsdyR1c2VyX2lkKSkgew0KICBmbHdfdG1sW1tpXV0gPC0gZ2V0X3RpbWVsaW5lKA0KICAgIGZsdyR1c2VyX2lkW2ldLCBuID0gMTANCiAgKQ0KICBpZiAoaSAlJSA1NiA9PSAwTCkgew0KICAgIHJsIDwtIHJhdGVfbGltaXQoImdldF90aW1lbGluZSIpDQogICAgU3lzLnNsZWVwKGFzLm51bWVyaWMocmwkcmVzZXQsICJzZWNzIikpDQogIH0NCiAgY2F0KGksICIgIikNCn0NCg0KYXRfcmR0IDwtIHJ0d2VldDo6c2VhcmNoX3R3ZWV0cygNCiAgInRvOkNlcm5vdmljaCIsIA0KICBuID0gNWU2LA0KICBzaW5jZSA9ICIyMDE3LTAxLTAxIiwNCiAgdW50aWwgPSAiMjAxOC0wMS0wMSIsDQogICByZXRyeW9ucmF0ZWxpbWl0ID0gVFJVRQ0KDQp0d2VldHMgPC0gdXNlclRpbWVsaW5lKCdNaWxsZW5uaWFsV29lcycsIG4gPSAzMjAwKQ0KDQojIGNvbnZlcnQgc3RhdHVzIG9iamVjdCB0byBkYXRhIGZyYW1lIGZvciBlYXNpZXIgbWFuaXB1bGF0aW9uDQp0d2VldHNkZiA8LSB0d0xpc3RUb0RGKHR3ZWV0cykNCg0KdHdlZXRzZGYgJT4lIA0KICBtdXRhdGUoZGF0ZSA9IGx1YnJpZGF0ZTo6YXNfZGF0ZShjcmVhdGVkKSkgJT4lDQogIGZpbHRlcihkYXRlID4gbHVicmlkYXRlOjphc19kYXRlKCIyMDE3LTAxLTAxIikgJiBkYXRlIDwgbHVicmlkYXRlOjphc19kYXRlKCIyMDE4LTAxLTAxIikpDQpgYGANCg0KDQpgYGB7cn0NCmxpYnJhcnkoaHR0cikNCg0KIyAxLiBGaW5kIE9BdXRoIHNldHRpbmdzIGZvciB0d2l0dGVyOg0KIyAgICBodHRwczovL2Rldi50d2l0dGVyLmNvbS9kb2NzL2F1dGgvb2F1dGgNCm9hdXRoX2VuZHBvaW50cygidHdpdHRlciIpDQoNCiMgMi4gUmVnaXN0ZXIgYW4gYXBwbGljYXRpb24gYXQgaHR0cHM6Ly9hcHBzLnR3aXR0ZXIuY29tLw0KIyAgICBNYWtlIHN1cmUgdG8gc2V0IGNhbGxiYWNrIHVybCB0byAiaHR0cDovLzEyNy4wLjAuMToxNDEwLyINCiMNCiMgICAgUmVwbGFjZSBrZXkgYW5kIHNlY3JldCBiZWxvdw0KbXlhcHAgPC0gb2F1dGhfYXBwKCJ0d2l0dGVyIiwNCiAga2V5ID0gIlRZcldGUGtGQWtuNEc1QmJrV0lOWXciLA0KICBzZWNyZXQgPSAicWpPa21LWVU5a1dmVUZXbWVrSnV1NXR6dEU5YUVmTGJ0MjZXbGhaTDgiDQopDQoNCiMgMy4gR2V0IE9BdXRoIGNyZWRlbnRpYWxzDQp0d2l0dGVyX3Rva2VuIDwtIG9hdXRoMS4wX3Rva2VuKG9hdXRoX2VuZHBvaW50cygidHdpdHRlciIpLCBteWFwcCkNCg0KIyMgNC4gVXNlIEFQSQ0KI3JlcSA8LSBHRVQoImh0dHBzOi8vYXBpLnR3aXR0ZXIuY29tLzEuMS9zdGF0dXNlcy9ob21lX3RpbWVsaW5lLmpzb24iLA0KIyAgY29uZmlnKHRva2VuID0gdHdpdHRlcl90b2tlbikpDQojc3RvcF9mb3Jfc3RhdHVzKHJlcSkNCiNjb250ZW50KHJlcSkNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkocnR3ZWV0KQ0KbGlicmFyeShpZ3JhcGgpDQpsaWJyYXJ5KGhyYnJ0aGVtZXMpDQpsaWJyYXJ5KGdncmFwaCkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KcnN0YXRzIDwtIHNlYXJjaF90d2VldHMoIiNhbnRpd2hpdGUiLCBuPTIwMDAwKQ0KDQojIHNhbWUgYXMgcHJldmlvdXMgcmVjaXBlDQpmaWx0ZXIocnN0YXRzLCByZXR3ZWV0X2NvdW50ID4gMCkgJT4lIA0KICBzZWxlY3Qoc2NyZWVuX25hbWUsIG1lbnRpb25zX3NjcmVlbl9uYW1lKSAlPiUNCiAgdW5uZXN0KG1lbnRpb25zX3NjcmVlbl9uYW1lKSAlPiUgDQogIGZpbHRlcighaXMubmEobWVudGlvbnNfc2NyZWVuX25hbWUpKSAlPiUgDQogIGdyYXBoX2Zyb21fZGF0YV9mcmFtZSgpIC0+IHJ0X2cNCg0KDQpWKHJ0X2cpJG5vZGVfbGFiZWwgPC0gdW5uYW1lKGlmZWxzZShkZWdyZWUocnRfZylbVihydF9nKV0gPiAyMCwgbmFtZXMoVihydF9nKSksICIiKSkgDQpWKHJ0X2cpJG5vZGVfc2l6ZSA8LSB1bm5hbWUoaWZlbHNlKGRlZ3JlZShydF9nKVtWKHJ0X2cpXSA+IDIwLCBkZWdyZWUocnRfZyksIDApKSANCg0KZ2dyYXBoKHJ0X2csIGxheW91dCA9ICdsaW5lYXInLCBjaXJjdWxhciA9IFRSVUUpICsgDQogIGdlb21fZWRnZV9hcmMoZWRnZV93aWR0aD0wLjEyNSwgYWVzKGFscGhhPS4uaW5kZXguLikpICsNCiAgZ2VvbV9ub2RlX2xhYmVsKGFlcyhsYWJlbD1ub2RlX2xhYmVsLCBzaXplPW5vZGVfc2l6ZSksDQogICAgICAgICAgICAgICAgICBsYWJlbC5zaXplPTAsIGZpbGw9IiNmZmZmZmY2NiIsIHNlZ21lbnQuY29sb3VyPSJzcHJpbmdncmVlbiIsDQogICAgICAgICAgICAgICAgICBjb2xvcj0ic2xhdGVibHVlIiwgcmVwZWw9VFJVRSwgZmFtaWx5PWZvbnRfcmMsIGZvbnRmYWNlPSJib2xkIikgKw0KICBjb29yZF9maXhlZCgpICsNCiAgc2NhbGVfc2l6ZV9hcmVhKHRyYW5zPSJzcXJ0IikgKw0KICBsYWJzKHRpdGxlPSJSZXR3ZWV0IFJlbGF0aW9uc2hpcHMiLCBzdWJ0aXRsZT0iTW9zdCByZXR3ZWV0ZWQgc2NyZWVuIG5hbWVzIGxhYmVsZWQuIERhcmtlcnMgZWRnZXMgPT0gbW9yZSByZXR3ZWV0cy4gTm9kZSBzaXplID09IGxhcmdlciBkZWdyZWUiKSArDQogIHRoZW1lX2dyYXBoKGJhc2VfZmFtaWx5PWZvbnRfcmMpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikNCg0KDQpnZ3NhdmUoZmlsZSA9IGhlcmUoImltYWdlcyIsIm5ldHdvcms1LnBuZyIpKQ0KYGBgDQoNCg0KDQoNCmBgYHtyfQ0KbWFwX2NocjIgPC0gZnVuY3Rpb24oeCwgLmYsIC4uLikgew0KICBtYXAoeCwgLmYsIC4uLikgJT4lIG1hcF9pZihpc19lbXB0eSwgfiBOQV9jaGFyYWN0ZXJfKSAlPiUgZmxhdHRlbl9jaHIoKQ0KfQ0KZWxsaXBzaXplIDwtIGZ1bmN0aW9uKHgsIG4gPSAyMCkgew0KICBpZmVsc2Uoc3RyX2xlbmd0aCh4KSA+IG4sDQogICAgICAgICBwYXN0ZTAoc3RyX3N1Yih4LCBlbmQgPSBuIC0gMSksICJcdTIwMjYiKSwNCiAgICAgICAgIHN0cl9zdWIoeCwgZW5kID0gbikpICU+JQ0KICAgIHN0cl9wYWQobikNCn0NCg0KbXQgPC0gbWVudGlvbnMoImNubiIsIG4gPSAyMDAsIHNpbmNlSUQgPSBjbm5faWRzWzFdKQ0KbGVuZ3RoKG10KQ0KDQpkZiA8LSBkYXRhX2ZyYW1lKG10ID0gbXQpICU+JQ0KICBtdXRhdGUocmVwbHlUb1NJRCA9IG10ICU+JSBtYXBfY2hyMigicmVwbHlUb1NJRCIpKSAlPiUNCiAgZmlsdGVyKHJlcGx5VG9TSUQgPT0gdGFyZ2V0X3R3ZWV0X2lkKQ0KZGYgJT4lDQogIG11dGF0ZShpZCA9IG10ICU+JSBtYXBfY2hyMigiaWQiKSwNCiAgICAgICAgIHNjcmVlbk5hbWUgPSBtdCAlPiUgbWFwX2NocjIoInNjcmVlbk5hbWUiKSwNCiAgICAgICAgIHRleHQgPSBtdCAlPiUgbWFwX2NocjIoInRleHQiKSkgJT4lDQogIG11dGF0ZSh0ZXh0ID0gdGV4dCAlPiUgc3Vic3RyKDEzLCAxNDApICU+JSB0cmltd3MoKSAlPiUgZWxsaXBzaXplKDMwKSkgJT4lDQogIHNlbGVjdCgtcmVwbHlUb1NJRCwgLW10KQ0KDQpydHdlZXQ6Omxvb2t1cF90d2VldHMoY25uX2lkc1sxXSkNCg0KDQojI3NldCBuYW1lIG9mIHR3ZWV0ZXIgdG8gbG9vayBhdCAodGhpcyBjYW4gYmUgY2hhbmdlZCkNCnRhcmdldHR3aXR0ZXJuYW1lIDwtICJjbm4iDQoNCiMjZ2V0IHRoaXMgdHdlZXRlcidzIHRpbWVsaW5lDQp0bWxzIDwtIHJ0d2VldDo6Z2V0X3RpbWVsaW5lKHRhcmdldHR3aXR0ZXJuYW1lLCBuPTEwMCwgcmV0cnlvbnJhdGVsaW1pdD1UUlVFKQ0KIyNnZXQgdGhlaXIgdXNlciBpZA0KdGFyZ2V0dHdpdHRlcnVzZXJpZCA8LSBhcy5udW1lcmljKHNlbGVjdChydHdlZXQ6Omxvb2t1cF91c2Vycyh0YXJnZXR0d2l0dGVybmFtZSksIHVzZXJfaWQpKQ0KIyNnZXQgaWRzIG9mIHRoZWlyIHR3ZWV0cw0KdHdlZXRpZHMgPC0gc2VsZWN0KHRtbHMsIHN0YXR1c19pZCkNCnR3ZWV0aWRzIDwtIHRyYW5zZm9ybSh0d2VldGlkcywgc3RhdHVzX2lkX251bT1hcy5udW1lcmljKHN0YXR1c19pZCkpDQoNCiMjZ2V0IGxpc3Qgb2YgZm9sbG93ZXJzICh3aG8gYXJlIG1vc3QgbGlrZWx5IHRvIHJlcGx5KQ0KdGFyZ2V0Zm9sbG93ZXJzIDwtIGRhdGEuZnJhbWUocnR3ZWV0OjpnZXRfZm9sbG93ZXJzKHRhcmdldHR3aXR0ZXJuYW1lKSkNCg0KIyNjbGVhbiB1cCBmb2xsb3dlciBsaXN0IHRvIGV4Y2x1ZGUgdGhvc2UgdGhhdCBoYXZlIG5ldmVyIHR3ZWV0ZWQgYW5kIHJlc3RyaWN0ZWQgYWNjZXNzDQp1c2VyX2xvb2t1cCA8LSBydHdlZXQ6Omxvb2t1cF91c2Vycyh0YXJnZXRmb2xsb3dlcnMpDQp1c2Vyc193aXRoX3R3ZWV0c19hbmRfdW5wcm90ZWN0ZWQgPC0gZmlsdGVyKHVzZXJfbG9va3VwLCBzdGF0dXNlc19jb3VudCAhPSAwKQ0KdXNlcnNfd2l0aF90d2VldHNfYW5kX3VucHJvdGVjdGVkIDwtIHNlbGVjdChmaWx0ZXIodXNlcnNfd2l0aF90d2VldHNfYW5kX3VucHJvdGVjdGVkLCBwcm90ZWN0ZWQgIT0gIlRSVUUiKSwgdXNlcl9pZCkNCg0KdGFyZ2V0Zm9sbG93ZXJzIDwtIGZpbHRlcih0YXJnZXRmb2xsb3dlcnMsIHVzZXJfaWQgJWluJSB1c2Vyc193aXRoX3R3ZWV0c19hbmRfdW5wcm90ZWN0ZWQkdXNlcl9pZCkNCm9wdGlvbnMoc2NpcGVuID0gOTk5KQ0KZ2V0Zm9sbG93ZXJzcmVwbGllcyA8LSBmdW5jdGlvbih4KXsNCiAgZm9sbG93ZXIgPC0gYXMubnVtZXJpYyh4WzE6NTAwXSkNCiAgZm9sbG93ZXJ0bCA8LSBkYXRhLmZyYW1lKHJ0d2VldDo6Z2V0X3RpbWVsaW5lKGZvbGxvd2VyLCBuPTMyMDAsIHJldHJ5b25yYXRlbGltaXQ9VFJVRSkpDQogIGZvbGxvd2VydGwgPC0gZmlsdGVyKGZvbGxvd2VydGwsIHJlcGx5X3RvX3VzZXJfaWQgPT0gdGFyZ2V0dHdpdHRlcnVzZXJpZCkNCiAgZm9sbG93ZXJ0bCA8LSB0cmFuc2Zvcm0oZm9sbG93ZXJ0bCwgcmVwbHlfdG9fc3RhdHVzX2lkX251bT1hcy5udW1lcmljKHJlcGx5X3RvX3VzZXJfaWQpKQ0KICBqb2luIDwtIGlubmVyX2pvaW4oZm9sbG93ZXJ0bCwgdHdlZXRpZHMsIGJ5PWMoInJlcGx5X3RvX3N0YXR1c19pZF9udW0iPSJzdGF0dXNfaWRfbnVtIikpDQogIHJlcGx5Y291bnRzIDwtIGRhdGEuZnJhbWUoDQogICAgICAgICAgICAgICAgICBqb2luICU+JQ0KICAgICAgICAgICAgICAgICAgICBncm91cF9ieSh1c2VyX2lkLCByZXBseV90b19zdGF0dXNfaWRfbnVtKSAlPiUNCiAgICAgICAgICAgICAgICAgICAgc3VtbWFyaXNlKG49bigpKQ0KICAgICAgICAgICAgICAgICAgKQ0KICByZXR1cm4ocmVwbHljb3VudHMpDQp9DQoNCnR3ZWV0X3JlcGxpZXMgPC0gZG8uY2FsbCgicmJpbmQiLCBsYXBwbHkodGFyZ2V0Zm9sbG93ZXJzJHVzZXJfaWQsIGdldGZvbGxvd2Vyc3JlcGxpZXMpKQ0KDQpzcyA8LSBnZXRmb2xsb3dlcnNyZXBsaWVzKHggPSB0YXJnZXRmb2xsb3dlcnMkdXNlcl9pZCkNCg0KZmx3IDwtIHJ0d2VldDo6Z2V0X2ZvbGxvd2VycygicmVhbERvbmFsZFRydW1wIiwgbiA9IDIpDQoNCmZsd190bWwgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoKGZsdyR1c2VyX2lkKSkNCmZvciAoaSBpbiBzZXFfYWxvbmcoZmx3JHVzZXJfaWQpKSB7DQogIGZsd190bWxbW2ldXSA8LSBydHdlZXQ6OmdldF90aW1lbGluZSgNCiAgICBmbHckdXNlcl9pZFtpXSwgbiA9IDMyMDANCiAgKQ0KICBpZiAoaSAlJSA1NiA9PSAwTCkgew0KICAgIHJsIDwtIHJhdGVfbGltaXQoImdldF90aW1lbGluZSIpDQogICAgU3lzLnNsZWVwKGFzLm51bWVyaWMocmwkcmVzZXQsICJzZWNzIikpDQogIH0NCiAgY2F0KGksICIgIikNCn0NCmBgYA0KDQo=